from django.shortcuts import render
from urllib.request import urlopen
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.views import APIView
from django.conf import settings
from urllib.parse import urlencode, parse_qs
from rest_framework.response import Response
from .utils import QQOauthTool
from oauth.models import OAuthQQUser
from .serializers import QQTokenSerializer
from rest_framework_jwt.settings import api_settings
# import ssl
# ssl._create_default_https_context = ssl._create_unverified_context
# import ssl
# context = ssl._create_unverified_context()

# Create your views here.


"""
# urllib.parse.urlencode(query)
# 
# 将query字典转换为url路径中的查询字符串
# 
# urllib.parse.parse_qs(qs)
# 
# 将qs查询字符串格式数据转换为python的字典
# 
# urllib.request.urlopen(url, data=None)
# 
# 发送http请求，如果data为None，发送GET请求，如果data不为None，发送POST请求
# 
# 返回response响应对象，可以通过read()读取响应体数据，需要注意读取出的响应体数据为bytes类型
"""""
# 1.浏览器请求服务器的时候需要生成一个url
# 2.通过用户的扫描生成一个code
# 3.通过code换去token
# 4.通过token换openid


# APIView
class QQOauthURLView(APIView):
    """
    GET      /oauth/qq/statues/
    根据腾讯提供的接口文档生成一个url
    """""

    def get(self, request):
        """
        # 生成auth_url
        # https://graph.qq.com/oauth2.0/authorize
        # 请求参数请包含如下内容：
        # response_type   必须      授权类型，此值固定为“code”。
        # client_id       必须      申请QQ登录成功后，分配给应用的appid。
        # redirect_uri    必须      成功授权后的回调地址，必须是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
        # state           必须      client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
        # scope              可选      scope=get_user_info

        :param request: 
        :return: 
        """""
        # 获取state
        state = request.query_params.get('state')

        # base_url最后要添加问号用来拼接参数
        # base_url = 'https://graph.qq.com/oauth2.0/authorize?'

        # 组织一个字典,使用这个字典存放参数
        # params = {
        #     'response_type': 'code',
        #     'client_id': settings.QQ_APP_ID,
        #     'redirect_uri': settings.QQ_REDIRECT_URL,
        #     'state': state,
        #     'scope': 'get_user_info',
        # }

        # 需要将字典的参数拼接到base_url中
        # urllib.parse.urlendoce(query)
        # 将query字典转换为url路径中的查询字符串

        # auth_url = base_url + urlencode(params)
        qq = QQOauthTool()
        auth_url = qq.get_oauth_url(state)

        return Response({"auth_url": auth_url})


# post中需要用到序列化器
class QQTokenView(GenericAPIView):

    serializer_class = QQTokenSerializer

    """
    GET  /oauth/qq/?code=xxx
    通过获取的 code来换取token
    """""
    def get(self, request):
        """
        # PC网站：https://graph.qq.com/oauth2.0/token
        # GET
        # grant_type      必须      授权类型，在本步骤中，此值为“authorization_code”。
        # client_id       必须      申请QQ登录成功后，分配给网站的appid。
        # client_secret   必须      申请QQ登录成功后，分配给网站的appkey。
        # code            必须      上一步返回的authorization
        # redirect_uri    必须      与上面一步中传入的redirect_uri保持一致。

        :param request: 
        :return: 
        """""

        code = request.query_params.get('code')
        if code is None:
            return Response({'message': '缺少参数'}, status=status.HTTP_400_BAD_REQUEST)

        # # 准备url,注意添加?
        # base_url = 'https://graph.qq.com/oauth2.0/token?'
        #
        # params = {
        #     'grant_type': 'authorization_code',
        #     'client_id': settings.QQ_APP_ID,
        #     'client_secret': settings.QQ_APP_KEY,
        #     'code': code,
        #     'redirect_uri': settings.QQ_REDIRECT_URL
        # }
        #
        # url = base_url + urlencode(params)
        #
        # # 获取数据
        # # 通过url_open来请求url中的数据
        # # response = urlopen(url)
        # #
        # # data = response.read().decode()
        # try:
        #     resp = urlopen(url, context=context)
        #     data = resp.read().decode()
        # except Exception as e:
        #     print(e)
        #
        # dict = parse_qs(data)
        # # print(dict)
        # access_tokens = dict.get('access_token')
        # if access_tokens:
        #     access_token = access_tokens[0]
        # print(access_token)
        qq = QQOauthTool()
        access_token = qq.get_token_by_code(code)

        openid = qq.get_openid_by_token(access_token)

        if not openid:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # 获取到openid
        # 根据openid来判断用户之前是否有绑定过
        try:
            qquser = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 没有绑定过
            # 需要绑定
            token = OAuthQQUser.generic_token_by_openid(openid)
            return Response({'access_token': token})
        else:
            # 没有异常的时候执行else
            # 绑定过,让它直接登录
            # 返回token
            user = qquser.user
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            qquser.token = token

            return Response({
                'token': token,
                'user_id': user.id,
                'user_name': user.username
            })

    def post(self, request):
        """
        1.当用户点击保存的时候,需要把access_token(openid),手机号,密码,短息验证码,使用post方式提交过来
        2.access_token,短信验证码需要进行校验
        3.需要将user和openid保存入库
        :param request: 
        :return: 
        """""

        # 1.获取数据,校验数据
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid()
        # 因为生成token需要user的信息,所以在create方法中返回了user
        user = serializer.save()

        # 返回token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        user.token = token

        return Response({
            'token': token,
            'user_id': user.id,
            'user_name': user.username
        })


